package com.koron.css2.newProjectCenter.task;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.ObjectUtil;
import com.koron.css2.baseConfig.mapper.ConfigMapper;
import com.koron.css2.baseConfig.mapper.ConfigVacationMapper;
import com.koron.css2.baseConfig.mapper.PubReceiptMapper;
import com.koron.css2.baseConfig.vo.ConfigVacationVO;
import com.koron.css2.newProjectCenter.Enum.PjInfoProcessStateEnum;
import com.koron.css2.newProjectCenter.bean.PjInfoBean;
import com.koron.css2.newProjectCenter.bean.PjProcessNodeTimePostponeBean;
import com.koron.css2.newProjectCenter.bean.PjWeekdayMonth;
import com.koron.css2.newProjectCenter.mapper.PjInfoMapper;
import com.koron.css2.newProjectCenter.mapper.PjProcessNodeTimePostponeMapper;
import com.koron.css2.newProjectCenter.mapper.PjWeekdayMonthMapper;
import com.koron.css2.newProjectCenter.vo.PjInfoListVO;
import com.koron.css2.serviceManage.bean.ProcessNodeBean;
import com.koron.css2.workflow.WorkflowImpl;
import com.koron.css2.workflow.bean.HistoryTaskMsgBean;
import com.koron.util.DBSourceUtils;
import com.koron.util.DateUtils;
import com.koron.util.Tools;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.SqlTask;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.swan.bean.MessageBean;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: ；lwc
 * @Date: 2023/11/10/15:25
 * @Description:
 */
@Component
@Slf4j
public class PjTimerTask {
    private static final String KEY = "PJ_TIMER";
    @Autowired
    private RedissonClient redissonClient;

    @Scheduled(cron = "0 0 3 * * ? ")
    //@Scheduled(cron = "0 0/2 * * * ? ")
    public void timerTask() {
        List<String> companys = DBSourceUtils.getCompanyNoList();
        //List<String> companys = Arrays.asList("C021903");
        for (String companyNo : companys) {
            StringBuffer key = new StringBuffer(KEY).append(":");
            key.append(companyNo);
            RLock lock = redissonClient.getLock(key.toString());
            try {

                String dbEnv = DBSourceUtils.getDbEnv(companyNo);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        ADOConnection.runTask(dbEnv, PjTimerTask.class, "timerCompute", companyNo, lock,null);
                    }
                }).start();

            } catch (Exception e) {
                log.error(companyNo + e.getMessage(), e);
                continue;
            }
        }


    }

    @TaskAnnotation("timerCompute")
    public  void timerCompute(SessionFactory factory, String companyNo, RLock lock,String billNo) throws Exception {
        try {
            if (lock.tryLock()) {
                StopWatch stopWatch = new StopWatch();
                stopWatch.start();

                PjInfoMapper pjInfoMapper = factory.getMapper(PjInfoMapper.class);


                PubReceiptMapper pubmapper = factory.getMapper(PubReceiptMapper.class);
                String setCode = pubmapper.getWorkflowApp(companyNo);

                ConfigMapper configMapper = factory.getMapper(ConfigMapper.class);
                String pj_filter_vacation = configMapper.getConfigValueByName("PJ_FILTER_VACATION");
                String pj_filter_weekday = configMapper.getConfigValueByName("PJ_FILTER_WEEKDAY");


                List<PjInfoListVO> pjInfoListVOS = pjInfoMapper.selectNormalList(billNo);//单据积攒不流转

                ZoneId zoneId = ZoneId.systemDefault();
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                ConfigVacationMapper configVacationMapper = factory.getMapper(ConfigVacationMapper.class);
                List<ConfigVacationVO> vacationVOList = configVacationMapper.selectConfigVacationList(null);
                Map<LocalDateTime, LocalDateTime> vacationDays = new HashMap<>();
                vacationVOList.stream().forEach(x -> {
                    String vacationBeginDate = x.getVacationBeginDate();
                    String vacationEndDate = x.getVacationEndDate();
                    Map<LocalDateTime, LocalDateTime> map = dayTimePeriod(LocalDate.parse(vacationBeginDate, dateFormatter).atStartOfDay(), LocalDate.parse(vacationEndDate, dateFormatter).atTime(23, 59), false);
                    vacationDays.putAll(map);
                });
                List<LocalDate> vacationList = vacationDays.values().stream().map(x -> x.toLocalDate()).collect(Collectors.toList());
                int successfulSum = 0;
                for (PjInfoListVO pjInfo : pjInfoListVOS) {
                    try {
                        ADOConnection.runTask(DBSourceUtils.getDbEnv(companyNo), new SqlTask() {
                            @SneakyThrows
                            @Override
                            public Object run(SessionFactory sessionFactory) {
                                PjInfoMapper pjInfoMapper1 = sessionFactory.getMapper(PjInfoMapper.class);
                                PjProcessNodeTimePostponeMapper mapper = sessionFactory.getMapper(PjProcessNodeTimePostponeMapper.class);
                                ConfigVacationMapper vacationMapper = factory.getMapper(ConfigVacationMapper.class);
                                PjWeekdayMonthMapper monthMapper = factory.getMapper(PjWeekdayMonthMapper.class);
                                PubReceiptMapper pubmapper2 = factory.getMapper(PubReceiptMapper.class, DBSourceUtils.getDbEnv(companyNo));
                                LocalDateTime pjStartTime = LocalDateTime.parse(pjInfo.getCreateTime(), dateTimeFormatter);
                                String pjInfoId = pjInfo.getId();
                                List<HistoryTaskMsgBean> historyTaskMsgList = new ArrayList<>();
                                if (StringUtils.isBlank(pjInfo.getProcessInstanceId())) {
                                    HistoryTaskMsgBean historyTaskMsgBean = new HistoryTaskMsgBean();
                                    historyTaskMsgBean.setNowNodeCode(PjInfoProcessStateEnum.REGISTER.getProcessState());
                                    historyTaskMsgBean.setNowNodeName(PjInfoProcessStateEnum.REGISTER.getProcessName());
                                    historyTaskMsgBean.setStartTime(pjInfo.getCreateTime());
                                    historyTaskMsgBean.setOperationTime(LocalDateTime.now().toString());
                                    historyTaskMsgList.add(historyTaskMsgBean);
                                } else {
                                    //historyTaskMsgList = WorkflowImpl.workflowhistory(setCode, "pj_info_new", "654b3e57ee66f90d6829be8e");
                                    historyTaskMsgList = WorkflowImpl.workflowhistory(setCode, "pj_info_new_" + pjInfo.getPjType(), pjInfo.getId());
                                    if (historyTaskMsgList.size() <= 0) {
                                        log.error("工作流查询审批历史错误:{}", historyTaskMsgList);
                                        throw new RuntimeException("工作流查询审批历史错误");
                                    }
                                    HistoryTaskMsgBean registerTask = historyTaskMsgList.get(0);
                                    String createTime = pjInfo.getCreateTime();
                                    String operationTime = registerTask.getOperationTime();
                                    LocalDateTime registerOperationTime = LocalDateTime.parse(operationTime, dateTimeFormatter);
                                    registerTask.setStartTime(pjStartTime.isBefore(registerOperationTime)?createTime:registerTask.getStartTime());

                                    HistoryTaskMsgBean nowTask = new HistoryTaskMsgBean();
                                    HistoryTaskMsgBean historyTaskMsgBean = historyTaskMsgList.get(historyTaskMsgList.size() - 1);
                                    nowTask.setNowNodeCode(pjInfo.getProcessState());
                                    nowTask.setNowNodeName(pjInfo.getProcessName());
                                    nowTask.setStartTime(historyTaskMsgBean.getOperationTime());
                                    nowTask.setOperationTime(LocalDateTime.now().format(dateTimeFormatter));
                                    historyTaskMsgList.add(nowTask);
                                }

                                List<PjProcessNodeTimePostponeBean> beanList = new ArrayList<>();
                                CompletableFuture<Map<String, Integer>> future1 = CompletableFuture.supplyAsync(new Supplier<Map<String, Integer>>() {
                                    @Override
                                    public Map<String, Integer> get() {
                                        Map<String, Integer> map = ADOConnection.runTask(DBSourceUtils.getDbEnv(companyNo), new SqlTask() {
                                            @Override
                                            public Object run(SessionFactory sessionFactory) {
                                                //ConfigVacationMapper vacationMapper1 = sessionFactory.getMapper(ConfigVacationMapper.class);
                                                PjWeekdayMonthMapper monthMapper1 = sessionFactory.getMapper(PjWeekdayMonthMapper.class);
                                                Map<String, Integer> stringIntegerMap = calcuteUsedDaysAndHours(pj_filter_vacation, pj_filter_weekday, pjStartTime, monthMapper1, vacationList);

                                                return stringIntegerMap;
                                            }
                                        }, Map.class);
                                        return map;
                                    }
                                });

                                for (HistoryTaskMsgBean taskMsgBean : historyTaskMsgList) {
                                    taskMsgBean.setStartTime(String.valueOf(DateUtil.parse(taskMsgBean.getStartTime())));
                                    long taskPlanHours = 0;
                                    long timeUsed = 0;
                                    PjProcessNodeTimePostponeBean pjProcessNodeTimePostpone = new PjProcessNodeTimePostponeBean();
                                    pjProcessNodeTimePostpone.setNodeCode(taskMsgBean.getNowNodeCode());
                                    pjProcessNodeTimePostpone.setBillNo(pjInfo.getBillNo());
                                    pjProcessNodeTimePostpone.setBillId(pjInfo.getId());
                                    pjProcessNodeTimePostpone.setId(Tools.getObjectId());
                                    pjProcessNodeTimePostpone.setOperator(taskMsgBean.getOperationUserName());
                                    pjProcessNodeTimePostpone.setComments(taskMsgBean.getComment());
                                    pjProcessNodeTimePostpone.setStartTime(DateUtils.parseDate(taskMsgBean.getStartTime()));
                                    pjProcessNodeTimePostpone.setComplateTime(DateUtils.parseDate(taskMsgBean.getOperationTime()));
                                    pjProcessNodeTimePostpone.setOperation(taskMsgBean.getOperation());
                                    pjProcessNodeTimePostpone.setTaskName(taskMsgBean.getNowNodeName());
                                    pjProcessNodeTimePostpone.setProcessInstanceId(pjInfo.getProcessInstanceId());

                                    if (StringUtils.isNotBlank(pjInfo.getPjType())) {
                                        Map<String, String> param2 = new HashMap<>();
                                        param2.put("receiptType", "pj_info_new#" + pjInfo.getPjType());
                                        param2.put("nodeCode", taskMsgBean.getNowNodeCode());
                                        List<ProcessNodeBean> processNodeList = pubmapper2.listProcessNodeByBillType(param2);
                                        if (processNodeList.size() > 0) {
                                            taskPlanHours = processNodeList.get(0).getTimeOut();
                                            pjProcessNodeTimePostpone.setPlanTime(Math.toIntExact(taskPlanHours));
                                        } else {
                                            pjProcessNodeTimePostpone.setPlanTime(0);
                                        }
                                    }

                                    LocalDateTime startTime = LocalDateTime.parse(taskMsgBean.getStartTime(), dateTimeFormatter);
                                    LocalDateTime endTime = LocalDateTime.parse(taskMsgBean.getOperationTime(), dateTimeFormatter);

                                    if ("1".equals(pj_filter_vacation) || "1".equals(pj_filter_weekday)) {
                                        //时间按天分割
                                        Map<LocalDateTime, LocalDateTime> duringPeriod = dayTimePeriod(startTime, endTime, true);
                                        //2、去除假日
                                        if ("1".equals(pj_filter_vacation)) {
                                            removeHolidays(duringPeriod, vacationList);
                                        }
                                        //3、去除非工作日时间段：上午、下午
                                        if ("1".equals(pj_filter_weekday)) {
                                            List<Integer> monthsWithinTimePeriod = DateUtils.monthsWithinTimePeriod(startTime, endTime);
                                            List<PjWeekdayMonth> weekdayMonths = monthMapper.listByMonths(monthsWithinTimePeriod);
                                            Map<Integer, List<PjWeekdayMonth>> groupMonth = new HashMap<>();
                                            if (ObjectUtil.isNotNull(weekdayMonths) && weekdayMonths.size() > 0) {
                                                groupMonth = weekdayMonths.stream().collect(Collectors.groupingBy(PjWeekdayMonth::getMonth));
                                            }
                                            Iterator<LocalDateTime> iterator3 = duringPeriod.keySet().iterator();
                                            List<Map<LocalDateTime, LocalDateTime>> result = new ArrayList<>();
                                            while (iterator3.hasNext()) {
                                                LocalDateTime start = iterator3.next();
                                                LocalDateTime end = duringPeriod.get(start);
                                                int month = start.getMonth().getValue();
                                                if (groupMonth.containsKey(month)) {
                                                    //去除非工作时间
                                                    PjWeekdayMonth pjWeekdayMonth = groupMonth.get(month).get(0);
                                                    LocalDateTime morningStart = LocalDateTime.ofInstant(pjWeekdayMonth.getMorningBeginDate().toInstant(), zoneId);
                                                    LocalTime morningStartTime = morningStart.toLocalTime();
                                                    LocalDateTime morningEnd = LocalDateTime.ofInstant(pjWeekdayMonth.getMorningEndDate().toInstant(), zoneId);
                                                    LocalTime morningEndTime = morningEnd.toLocalTime();
                                                    LocalDateTime afternoonBegin = LocalDateTime.ofInstant(pjWeekdayMonth.getAfternoonBeginDate().toInstant(), zoneId);
                                                    LocalTime afternoonStartTime = afternoonBegin.toLocalTime();
                                                    LocalDateTime afternoonEnd = LocalDateTime.ofInstant(pjWeekdayMonth.getAfternoonEndDate().toInstant(), zoneId);
                                                    LocalTime afternoonEndTime = afternoonEnd.toLocalTime();
                                                    //工作时间段
                                                    LocalDateTime morningStartPeriod = LocalDateTime.of(start.toLocalDate(), morningStartTime);
                                                    LocalDateTime morningEndPeriod = LocalDateTime.of(start.toLocalDate(), morningEndTime);

                                                    LocalDateTime afternoonStartPeriod = LocalDateTime.of(start.toLocalDate(), afternoonStartTime);
                                                    LocalDateTime afternoonEndPeriod = LocalDateTime.of(start.toLocalDate(), afternoonEndTime);
                                                    //获取与上午、下午工作时间和审批时间交集
                                                    Map<LocalDateTime, LocalDateTime> morningIntersections = DateUtils.getIntersections(morningStartPeriod, morningEndPeriod, start, end);
                                                    Map<LocalDateTime, LocalDateTime> afternoonIntersections = DateUtils.getIntersections(afternoonStartPeriod, afternoonEndPeriod, start, end);
                                                    if (ObjectUtil.isNotNull(morningIntersections) && morningIntersections.size() > 0) {
                                                        result.add(morningIntersections);
                                                    } else if (ObjectUtil.isNotNull(afternoonIntersections) && afternoonIntersections.size() > 0) {
                                                        result.add(afternoonIntersections);
                                                    }


                                                } else {
                                                    Map<LocalDateTime, LocalDateTime> defaultWeekday = new HashMap<>();
                                                    defaultWeekday.put(start, end);
                                                    result.add(defaultWeekday);
                                                }

                                            }
                                            for (Map<LocalDateTime, LocalDateTime> map : result) {
                                                Set<Map.Entry<LocalDateTime, LocalDateTime>> entries = map.entrySet();
                                                Optional<Map.Entry<LocalDateTime, LocalDateTime>> first = entries.stream().findFirst();
                                                Map.Entry<LocalDateTime, LocalDateTime> entry = first.get();
                                                LocalDateTime key = entry.getKey();
                                                LocalDateTime value = entry.getValue();
                                                long hours = Duration.between(key, value).toHours();//不满一小时不计算
                                                timeUsed += hours;
                                            }

                                        } else {
                                            //未开启配置
                                            timeUsed = duringPeriod.entrySet().stream().mapToInt(x -> {
                                                int duration = Math.toIntExact(Duration.between(x.getKey(), x.getValue()).toHours());
                                                return duration;
                                            }).sum();


                                        }
                                        if (0 == (taskPlanHours)) {//未配置超时时间直接未超时
                                            pjProcessNodeTimePostpone.setTimeOutFlag(0);
                                        } else {
                                            pjProcessNodeTimePostpone.setTimeOutFlag(Math.toIntExact((taskPlanHours - timeUsed)) >= 0 ? 0 : 1);
                                        }
                                        pjProcessNodeTimePostpone.setTimeConsum(Math.toIntExact(timeUsed));

                                    }else {
                                        timeUsed = Duration.between(startTime, endTime).toHours();
                                        pjProcessNodeTimePostpone.setTimeOutFlag(0);
                                        pjProcessNodeTimePostpone.setTimeConsum(Math.toIntExact(timeUsed));
                                    }
                                    beanList.add(pjProcessNodeTimePostpone);
                                }
                                mapper.deleteByBillId(pjInfoId);
                                //写入
                                mapper.batchInsert(beanList);
//                    int planSum = beanList.stream().mapToInt(PjProcessNodeTimePostponeBean::getPlanTime).sum();
                                long planSum = 0;
                                int usedSum = beanList.stream().mapToInt(PjProcessNodeTimePostponeBean::getTimeConsum).sum();
                                Map<String, String> param2 = new HashMap<>();
                                param2.put("receiptType", "pj_info_new#" + pjInfo.getPjType());
                                List<ProcessNodeBean> processNodeList = pubmapper2.listProcessNodeByBillType(param2);
                                if (ObjectUtil.isNotNull(processNodeList) && processNodeList.size() > 0) {
                                    planSum = processNodeList.stream().mapToLong(ProcessNodeBean::getTimeOut).sum();
                                }

                                LocalDateTime planTime = calculatePlannedCompletionTime(vacationMapper, monthMapper, pjStartTime, planSum, pj_filter_vacation, pj_filter_weekday, zoneId);

                                boolean whetherItIsOverdue = usedSum > planSum;
                                PjInfoBean infoBean = new PjInfoBean();
                                ZonedDateTime zonedDateTime = planTime.atZone(zoneId);
                                infoBean.setPlanTime(Date.from(zonedDateTime.toInstant()));
                                infoBean.setTimeOutFlag(whetherItIsOverdue ? 1 : 0);
                                infoBean.setId(pjInfoId);
                                infoBean.setPlanSum(Math.toIntExact(planSum));
                                infoBean.setUsedSum(usedSum);
                                // Map<String, Integer> future1Map = future1.get();
//                                Map<String, Integer> stringIntegerMap = calcuteUsedDaysAndHours(pj_filter_vacation, pj_filter_weekday, pjStartTime, monthMapper, vacationMapper);
                                Map<String, Integer> stringIntegerMap = future1.get();
                                Integer workDays = stringIntegerMap.get("workDays");
                                Integer workHours = stringIntegerMap.get("workHours");
                                // 如果计算出来的工作日小时数大于一天的24小时，则需要将小时继续换算为天数
                                if (workHours != null && workHours > 24){
                                    int iDay = workHours / 24;
                                    int iHour = workHours % 24;
                                    workDays = workDays + iDay;
                                    workHours = iHour;
                                }
                                infoBean.setWorkDays(workDays);
                                infoBean.setWorkHours(workHours);
                                infoBean.setPlanSum(Math.toIntExact(planSum));
                                pjInfoMapper1.updateTimer(infoBean);


//                            Integer usedWorkDay=0 ;
//                              //不满足一整个工作日的小时
//                            Integer usedWorkHours=0 ;

                                return null;

                            }

                        }, MessageBean.class);
                        successfulSum++;

                    } catch (Exception e) {
                        log.error(pjInfo.getBillNo() + "时间更新失败：" + e.getMessage(), e);
                    }


                }
                stopWatch.stop();
                double totalTimeSeconds = stopWatch.getTotalTimeSeconds();
                log.info(companyNo + "更新工程共" + pjInfoListVOS.size() + "条，成功：{}条，用时：{} 秒", successfulSum, totalTimeSeconds);
                log.error(companyNo + "更新工程共" + pjInfoListVOS.size() + "条，成功：{}条，用时：{} 秒", successfulSum, totalTimeSeconds);

            }
        } catch (Exception e) {
            log.error(companyNo + "更新工程时间失败：" + e.getMessage(), e);
        } finally {
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }

    }

    private static Map<String, Integer> calcuteUsedDaysAndHours(String pj_filter_vacation, String pj_filter_weekday, LocalDateTime pjStartTime, PjWeekdayMonthMapper monthMapper, List<LocalDate> vacationList) {
        //计算已用符合工作日时间段的天、时
        //已用天数 符合上午、下午完整区间的工作天数
        long usedWorkDay = 0;
        //不满足一整个工作日的小时
        long usedWorkHours = 0;
        Map<String, Integer> resultMap = new HashMap<>();
        ZoneId zoneId = ZoneId.systemDefault();
        boolean filterVacation = "1".equals(pj_filter_vacation);
        boolean filterWeekDay = "1".equals(pj_filter_weekday);
        LocalDateTime now = LocalDateTime.now();
        if (filterVacation || filterWeekDay) {
            Map<LocalDateTime, LocalDateTime> periodMap = dayTimePeriod(pjStartTime, now, filterVacation);

            List<Integer> monthsWithinTimePeriod = DateUtils.monthsWithinTimePeriod(pjStartTime, LocalDateTime.now());
            List<PjWeekdayMonth> weekdayMonths = monthMapper.listByMonths(monthsWithinTimePeriod);
            Map<Integer, List<PjWeekdayMonth>> groupMonth = new HashMap<>();
            if (ObjectUtil.isNotNull(weekdayMonths) && weekdayMonths.size() > 0) {
                groupMonth = weekdayMonths.stream().collect(Collectors.groupingBy(PjWeekdayMonth::getMonth));
            }
            if (filterVacation) {
                removeHolidays(periodMap, vacationList);
            }
            Set<LocalDateTime> keySet = periodMap.keySet();

            for (LocalDateTime localDateTime : keySet) {
                LocalDateTime endTime = periodMap.get(localDateTime);
                int month = localDateTime.getMonth().getValue();
                //是否配置了月份工作时间
                if (filterWeekDay && groupMonth.containsKey(month)) {
                    if (localDateTime.isEqual(pjStartTime) || now.isEqual(endTime)) {
                        List<Map<LocalDateTime, LocalDateTime>> result = new ArrayList<>();
                        PjWeekdayMonth pjWeekdayMonth = groupMonth.get(month).get(0);
                        LocalDateTime morningStart = LocalDateTime.ofInstant(pjWeekdayMonth.getMorningBeginDate().toInstant(), zoneId);
                        LocalTime morningStartTime = morningStart.toLocalTime();
                        LocalDateTime morningEnd = LocalDateTime.ofInstant(pjWeekdayMonth.getMorningEndDate().toInstant(), zoneId);
                        LocalTime morningEndTime = morningEnd.toLocalTime();
                        LocalDateTime afternoonBegin = LocalDateTime.ofInstant(pjWeekdayMonth.getAfternoonBeginDate().toInstant(), zoneId);
                        LocalTime afternoonStartTime = afternoonBegin.toLocalTime();
                        LocalDateTime afternoonEnd = LocalDateTime.ofInstant(pjWeekdayMonth.getAfternoonEndDate().toInstant(), zoneId);
                        LocalTime afternoonEndTime = afternoonEnd.toLocalTime();
                        //工作时间段
                        LocalDateTime morningStartPeriod = LocalDateTime.of(localDateTime.toLocalDate(), morningStartTime);
                        LocalDateTime morningEndPeriod = LocalDateTime.of(localDateTime.toLocalDate(), morningEndTime);

                        LocalDateTime afternoonStartPeriod = LocalDateTime.of(localDateTime.toLocalDate(), afternoonStartTime);
                        LocalDateTime afternoonEndPeriod = LocalDateTime.of(localDateTime.toLocalDate(), afternoonEndTime);
                        //获取与上午、下午工作时间和审批时间交集
                        Map<LocalDateTime, LocalDateTime> morningIntersections = DateUtils.getIntersections(morningStartPeriod, morningEndPeriod, localDateTime, endTime);
                        Map<LocalDateTime, LocalDateTime> afternoonIntersections = DateUtils.getIntersections(afternoonStartPeriod, afternoonEndPeriod, localDateTime, endTime);

                        if (ObjectUtil.isNotNull(morningIntersections) && morningIntersections.size() > 0) {
                            result.add(morningIntersections);
                        }
                        if (ObjectUtil.isNotNull(afternoonIntersections) && afternoonIntersections.size() > 0) {
                            result.add(afternoonIntersections);
                        }
                        for (Map<LocalDateTime, LocalDateTime> map : result) {
                            Set<Map.Entry<LocalDateTime, LocalDateTime>> entries = map.entrySet();
                            Optional<Map.Entry<LocalDateTime, LocalDateTime>> first = entries.stream().findFirst();
                            Map.Entry<LocalDateTime, LocalDateTime> localDateTimeLocalDateTimeEntry = first.get();
                            LocalDateTime key = localDateTimeLocalDateTimeEntry.getKey();
                            LocalDateTime value = localDateTimeLocalDateTimeEntry.getValue();
                            long hours = Duration.between(key, value).toHours();//不满一小时不计算
                            usedWorkHours += hours;
                        }
                    } else {
                        usedWorkDay += 1;
                    }
                } else {
                    if (localDateTime.isEqual(pjStartTime) || now.isEqual(endTime)) {
                        long hours = Duration.between(localDateTime, endTime).toHours();//不满一小时不计算
                        usedWorkHours += hours;
                    } else {
                        usedWorkDay += 1;
                    }
                }

            }


        } else {
            //未配置
            usedWorkDay = Math.toIntExact(Duration.between(pjStartTime, LocalDateTime.now()).toDays());
            long toHours = Duration.between(pjStartTime, LocalDateTime.now()).toHours();
            if (toHours > 0) {
                usedWorkHours = Math.toIntExact(toHours % 24);
            }
        }
        //log.info("开始时间：{},pjStartTime)
        //log.info("天------------" + usedWorkDay);
        //log.info("时--------------" + usedWorkHours);
        resultMap.put("workDays", Math.toIntExact(usedWorkDay));
        resultMap.put("workHours", Math.toIntExact(usedWorkHours));
        return resultMap;
    }

    private static LocalDateTime calculatePlannedCompletionTime(ConfigVacationMapper vacationMapper, PjWeekdayMonthMapper monthMapper, LocalDateTime pjStartTime, long planSum, String pj_filter_vacation, String pj_filter_weekday, ZoneId zoneId) {
        int trigger = 0;
        if ("1".equals(pj_filter_vacation) || "1".equals(pj_filter_weekday)) {
            while (planSum > 0) {
                trigger++;
                if (trigger > planSum) return pjStartTime;
                if ("1".equals(pj_filter_vacation)) {
                    Integer integer = vacationMapper.whetherItsAHolidayOrNot(pjStartTime.toString());
                    DayOfWeek dayOfWeek = pjStartTime.getDayOfWeek();
                    int i = dayOfWeek.compareTo(DayOfWeek.SUNDAY);
                    int j = dayOfWeek.compareTo(DayOfWeek.SATURDAY);
                    if (integer > 0 || i == 0 || j == 0) {
                        pjStartTime = LocalDateTime.of(pjStartTime.toLocalDate().plusDays(1), LocalTime.of(0, 0));
                        continue;
                    }

                }
                if ("1".equals(pj_filter_weekday)) {

                    PjWeekdayMonth weekDay = monthMapper.getOneByMonth(pjStartTime.getMonth().getValue());
                    if (ObjectUtil.isNotNull(weekDay)) {
                        LocalDateTime morningStart = LocalDateTime.ofInstant(weekDay.getMorningBeginDate().toInstant(), zoneId);
                        LocalTime morningStartTime = morningStart.toLocalTime();//
                        LocalDateTime morningEnd = LocalDateTime.ofInstant(weekDay.getMorningEndDate().toInstant(), zoneId);
                        LocalTime morningEndTime = morningEnd.toLocalTime();//
                        LocalDateTime afternoonBegin = LocalDateTime.ofInstant(weekDay.getAfternoonBeginDate().toInstant(), zoneId);
                        LocalTime afternoonStartTime = afternoonBegin.toLocalTime();//
                        LocalDateTime afternoonEnd = LocalDateTime.ofInstant(weekDay.getAfternoonEndDate().toInstant(), zoneId);
                        LocalTime afternoonEndTime = afternoonEnd.toLocalTime();//
                        LocalDate pjDate = pjStartTime.toLocalDate();
                        LocalTime pjTime = pjStartTime.toLocalTime();
                        morningStart = LocalDateTime.of(pjDate, morningStartTime);
                        morningEnd = LocalDateTime.of(pjDate, morningEndTime);

                        afternoonBegin = LocalDateTime.of(pjDate, afternoonStartTime);
                        afternoonEnd = LocalDateTime.of(pjDate, afternoonEndTime);

                        //获取上午和下午的交集

                        Map<LocalDateTime, LocalDateTime> morning = DateUtils.getIntersections(morningStart, morningEnd, pjStartTime, morningEnd);

                        Map<LocalDateTime, LocalDateTime> afternoon = DateUtils.getIntersections(afternoonBegin, afternoonEnd, pjStartTime, afternoonEnd);
                        if (ObjectUtil.isNotEmpty(morning)) {
                            Set<Map.Entry<LocalDateTime, LocalDateTime>> entries = morning.entrySet();
                            Optional<Map.Entry<LocalDateTime, LocalDateTime>> first = entries.stream().findFirst();
                            Map.Entry<LocalDateTime, LocalDateTime> localDateTimeLocalDateTimeEntry = first.get();
                            LocalDateTime key = localDateTimeLocalDateTimeEntry.getKey();
                            LocalDateTime value = localDateTimeLocalDateTimeEntry.getValue();
                            long hours = Duration.between(key, value).toHours();
                            if (planSum <= hours) {
                                pjStartTime = key;
                                return pjStartTime.plusHours(planSum);
                            } else {
                                pjStartTime = value;
                                planSum -= hours;

                            }
                        }
                        if (ObjectUtil.isNotEmpty(afternoon)) {
                            Set<Map.Entry<LocalDateTime, LocalDateTime>> entries = afternoon.entrySet();
                            Optional<Map.Entry<LocalDateTime, LocalDateTime>> first = entries.stream().findFirst();
                            Map.Entry<LocalDateTime, LocalDateTime> localDateTimeLocalDateTimeEntry = first.get();
                            LocalDateTime key = localDateTimeLocalDateTimeEntry.getKey();
                            LocalDateTime value = localDateTimeLocalDateTimeEntry.getValue();
                            long hours = Duration.between(key, value).toHours();
                            if (planSum <= hours) {
                                pjStartTime = key;
                                return pjStartTime.plusHours(planSum);
                            } else {
                                pjStartTime = value;
                                planSum -= hours;
                            }
                        }


                    }


                }
                pjStartTime = LocalDateTime.of(pjStartTime.toLocalDate().plusDays(1), LocalTime.of(0, 0, 0));

            }
        }
        pjStartTime.plusHours(planSum);
        return pjStartTime;

    }

    private static void removeHolidays(Map<LocalDateTime, LocalDateTime> duringPeriod, List<LocalDate> vacationList) {
        Iterator<LocalDateTime> iterator = duringPeriod.keySet().iterator();
        List<LocalDateTime> containList = new ArrayList<>();
        while (iterator.hasNext()) {
            LocalDateTime start = iterator.next();
            if (vacationList.contains(start.toLocalDate())) {
                // duringPeriod.remove(start);
                containList.add(start);
            }
        }
        containList.stream().forEach(x -> duringPeriod.remove(x));
    }

    public static Map<LocalDateTime, LocalDateTime> dayTimePeriod(LocalDateTime startDate1, LocalDateTime endDate1, boolean removeWeekend) {
        Objects.requireNonNull(startDate1, "起始时间不能为空");
        Objects.requireNonNull(endDate1, "结束时间不能为空");

        if (startDate1.isAfter(endDate1)) {
            throw new RuntimeException(startDate1 + "起始日期不能大于结束日期" + endDate1);
        }
        Map<LocalDateTime, LocalDateTime> result = new HashMap<>();
        long days = 0;

        days = Duration.between(startDate1, endDate1).toDays();
        LocalTime localTime1 = startDate1.toLocalTime();
        LocalTime localTime2 = endDate1.toLocalTime();
        if ((localTime1.isAfter(localTime2))) {
            days++;
        }
        if (0 == (days)) {
            result.put(startDate1, endDate1);
            return result;
        }
        for (long i = 0; i <= days; i++) {
            LocalDateTime start;
            LocalDateTime end = null;

            if (i == 0) {
                start = startDate1;
                end = LocalDateTime.of(startDate1.toLocalDate().plusDays(1), LocalTime.MIN);
            } else {
                LocalDateTime startPlus = startDate1.plusDays(i);


                start = LocalDateTime.of(startPlus.toLocalDate(), LocalTime.MIN);
                end = LocalDateTime.of(startPlus.toLocalDate().plusDays(1), LocalTime.MIN);
                if (i == days) {
                    end = endDate1;
                }
            }

            result.put(start, end);
        }
        if (removeWeekend) {
            Iterator<LocalDateTime> iterator = result.keySet().iterator();
            List<LocalDateTime> weekends = new ArrayList<>();
            while (iterator.hasNext()) {
                LocalDateTime start = iterator.next();
                DayOfWeek dayOfWeek = start.getDayOfWeek();
                int i = dayOfWeek.compareTo(DayOfWeek.SUNDAY);
                int j = dayOfWeek.compareTo(DayOfWeek.SATURDAY);
                if (i == 0 || j == 0) {
                    weekends.add(start);
                }

            }
            weekends.forEach(x -> result.remove(x));
        }
        return result;

    }


}
